package com.wwdx.utils;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.tags.RequestContextAwareTag;

import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.DynamicAttributes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * JSP tag 分页
 * @author liguoliang
 */
public class PaginationTag extends RequestContextAwareTag implements DynamicAttributes {

    /**
     * 调整的url
     */
    private Integer total;
    /**
     * 是否显示当前页数和总页数
     */
    private Map<String, String> attrs = new HashMap<>();
    /**
     * 额外的html标签属性
     */
    private String url;
    /**
     * 是否显示当前页数和总页数
     */
    private String full = "true";

    @Override
    protected int doStartTagInternal() throws Exception {
        JspWriter out = pageContext.getOut();
        out.print(createTag());
        return EVAL_PAGE;
    }

    @Override
    public void setDynamicAttribute(String uri, String localName, Object value) {
        this.attrs.put(localName, String.valueOf(value));
    }

    /**
     * 获取下次发送的带参数的url，最后一个参数是page，值为空
     */
    private String getUrlWithParams() {
        Map<String, String[]> params = this.pageContext.getRequest().getParameterMap();
        StringBuilder sb = new StringBuilder();
        String page = "page";
        params.forEach((k,v)->{
            if (!page.equals(k)) {
                for (String val : v) {
                    sb.append(k).append("=").append(val).append("&");
                }
            }
        });
        sb.append("page=");
        return url + "?" + sb.toString();
    }

    private int getCurrentPage(int pageCount) {
        int p = 1;
        String page = this.pageContext.getRequest().getParameter("page");
        if (StringUtils.isBlank(page)) {
            return p;
        }
        p = Integer.valueOf(page);
        if (p > pageCount) {
            p = pageCount;
        }
        return p;
    }

    private int getPageCount() {
        int defaultRows = 10;
        if (total == 0) {
            return 1;
        }
        if (total % defaultRows == 0) {
            return total / defaultRows;
        } else {
            return (total / defaultRows) + 1;
        }
    }

    /**
     * 是否显示完整的分页，包含有当前页数和总页数
     */
    private boolean isFull() {
        return Boolean.valueOf(this.full) || "yes".equals(this.full);
    }

    private boolean hasPrevPage(int currPage, int pageCount) {
        return pageCount > 1 && currPage > 1 && currPage <= pageCount;
    }

    private boolean hasNextPage(int currPage, int pageCount) {
        return pageCount > 1 && currPage < pageCount;
    }

    private boolean hasFirstPage(int currPage) {
        return currPage > 1;
    }

    private boolean hasLastPage(int currPage, int pageCount) {
        return currPage < pageCount;
    }

    private int getPrevPage(int currPage) {
        currPage --;
        if (currPage < 1) {
            currPage = 1;
        }
        return currPage;
    }

    private int getNextPage(int currPage, int pageCount) {
        currPage ++;
        if (currPage > pageCount) {
            currPage = pageCount;
        }
        return currPage;
    }

    private ArrayList<Integer> getPageNums(int currPage, int pageCount) {
        ArrayList<Integer> nums = new ArrayList<>(pageCount);
        int count = 10;
        if (pageCount <= count) {
            for (int i = 0; i < pageCount; i++) {
                nums.add(i + 1);
            }
        } else {
            int first = currPage - 5;
            int last = currPage + 5;
            if (first < 1) {
                first = 0;
                last = count;
            } else if (last > pageCount) {
                first = pageCount - count;
                last = pageCount;
            }
            for (int i = first; i < last; i++) {
                nums.add(i + 1);
            }
        }
        return nums;
    }

    private String createPageInfoDiv(int currPage, int pageCount) {
        return String.format("<div>总数%s 当前第%s页 共%s页</div>", total, currPage, pageCount);
    }

    private String createLi(String href, Object inner, String cls) {
        if (href == null) {
            href = "javascript:;";
        }
        if (cls == null) {
            cls = "";
        }
        //转义单引号和双引号
        href = StringUtils.replace(href, "'", "&apos;");
        href = StringUtils.replace(href, "\"", "&quot;");
        return String.format("<li class='%s'><a href=\"%s\">%s</a></li>", cls, href, inner);
    }

    private String createDivAttrs() {
        StringBuilder sb = new StringBuilder();
        attrs.forEach((k,v)->{
            sb.append(" ");
            sb.append(k);
            sb.append("=");
            sb.append("'");
            sb.append(v);
            sb.append("'");
        });
        return sb.toString();
    }

    private String createTag() {
        String href = this.getUrlWithParams();
        int pageCount = this.getPageCount();
        int currPage = this.getCurrentPage(pageCount);
        int prevPage = this.getPrevPage(currPage);
        int nextPage = this.getNextPage(currPage, pageCount);

        StringBuilder sb = new StringBuilder();

        sb.append("<div class='row'>");
        sb.append("<div class='col-md-3'>");
        if (this.isFull()) {
            sb.append(this.createPageInfoDiv(currPage, pageCount));
        }
        sb.append("</div>");

        sb.append("<div class='col-md-9'>");
        sb.append(this.createDivAttrs());
        sb.append("<ul class='pagination'>");

        String prevPage2 = "上一页";
        String nextPage2 = "下一页";
        String firstPage = "首页";
        String lastPage = "尾页";

        // 首页
        if (this.hasFirstPage(currPage)) {
            sb.append(this.createLi(href + 1, firstPage, null));
        } else {
            sb.append(this.createLi(null, firstPage, "disabled"));
        }
        // 上一页
        if (this.hasPrevPage(currPage, pageCount)) {
            sb.append(this.createLi(href + prevPage, prevPage2, "previous"));
        } else {
            sb.append(this.createLi(null, prevPage2, "disabled"));
        }
        ArrayList<Integer> pageNums = this.getPageNums(currPage, pageCount);
        for (int i : pageNums) {
            if (currPage == i) {
                sb.append(this.createLi(href + i, i, "active"));
            } else {
                sb.append(this.createLi(href + i, i, null));
            }
        }
        // 下一页
        if (this.hasNextPage(currPage, pageCount)) {
            sb.append(this.createLi(href + nextPage, nextPage2, "next"));
        } else {
            sb.append(this.createLi(null, nextPage2, "disabled"));
        }
        // 尾页
        if (this.hasLastPage(currPage, pageCount)) {
            sb.append(this.createLi(href + pageCount, lastPage, null));
        } else {
            sb.append(this.createLi(null, lastPage, "disabled"));
        }
        sb.append("</ul>");
        sb.append("</div>");
        sb.append("</div>");
        return sb.toString();
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = this.pageContext.getServletContext().getContextPath() + url;
    }

    public Integer getTotal() {
        return total;
    }

    public void setTotal(Integer total) {
        this.total = total;
    }

    public Map<String, String> getAttrs() {
        return attrs;
    }

    public void setAttrs(Map<String, String> attrs) {
        this.attrs = attrs;
    }

    public String getFull() {
        return full;
    }

    public void setFull(String full) {
        this.full = full;
    }
}